/*
 * Copyright (C) 2000-2008 Jens Nixdorf and various contributors
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to
 * deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 * sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies of the Software, its documentation and marketing & publicity
 * materials, and acknowledgment shall be given in the documentation, materials
 * and software packages that this Software was used.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package org.mopore.jat.core;

import java.awt.MenuItem;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mopore.jat.core.externalplugins.ExternalPluginManager;
import org.mopore.jat.core.fadingmessage.calibration.CalibrationInfo;
import org.mopore.jat.core.fadingmessage.calibration.ICalibtrationAccessor;
import org.mopore.jat.core.messaging.Message;
import org.mopore.jat.core.messaging.MessageType;
import org.mopore.jat.gui.SysTrayProxy;
import org.mopore.jat.gui.Theme;
import org.mopore.jat.plugin.AbstractPlugin;
import org.mopore.jat.plugin.Email;
import org.mopore.jat.plugin.IPluginContext;
import org.mopore.jat.plugin.IPluginFileAccess;
import org.mopore.jat.plugin.IWindowController;
import org.mopore.jat.plugin.PluginException;
import org.mopore.jat.plugin.ThemeChangeDelegator;
import org.mopore.jat.util.ImageService;
import org.mopore.jat.util.MetaInformationService;
import org.mopore.jat.util.Version;


public class CorePlatformPlugin extends AbstractPlugin implements ICore, ICalibtrationAccessor {
	
	private static final String CAN_NOT_STORE_COREINFO = "Can not store core info";

	private static final String CAN_NOT_RETRIEVE_COREINFO = "can not retrieve core info!";
	
	private static final String IMAGES_POPUPICONS_PREFERENCES_GIF = "/images/popupicons/preferences.gif";

	private final Log log = LogFactory.getLog(getClass().getName());
	
	private IPluginContext context;

	private CoreInfo coreInfo;
	
	private final ExternalPluginManager externalPluginManager;
	
	private final ThemeChanger themeChanger;

	private CalibtrationAction calibrationAction;
	
	
	public CorePlatformPlugin(
			SysTrayProxy sysTrayProxy, 
			ThemeChangeDelegator themeChangeDelegator, 
			ExternalPluginManager externalPluginManager,
			IWindowController windowController
			) {
		ThemeChangeAction themeChangeAction = new ThemeChangeAction(sysTrayProxy, 
				themeChangeDelegator, this );
		this.themeChanger = new ThemeChanger( this, themeChangeAction, 
				windowController );

		this.externalPluginManager = externalPluginManager;
		calibrationAction = new CalibtrationAction( this );
	}
	
	
	@Override
	public void onPluginLoadImpl(IPluginContext pluginContext) {
		this.context = pluginContext;
		this.coreInfo = getCoreInfo();
	}

	@Override
	protected Email getAuthorsEmailImpl() throws Exception{
		return MetaInformationService.readProjectHeadEmail();
	}

	@Override
	protected String getAuthorsNameImpl() {
		return MetaInformationService.readProjectHeadName();
	}

	@Override
	public String getDisplayNameImpl() {
		return "setup solution";
	}

	@Override
	public BufferedImage getPluginIcon() {
		BufferedImage image = 
			ImageService.load( IMAGES_POPUPICONS_PREFERENCES_GIF );
		return image;
	}

	@Override
	protected String getPluginNameImpl() {
		return CorePlatformPlugin.class.getName();
	}

	@Override
	public MenuItem[] getMenuFocusActions() {
		return null;
	}

	@Override
	public MenuItem[] getMenuActions( MenuItem base ) {
		
		MenuItem pluginManagerMenuItem = new MenuItem( "manage plugins" );
		pluginManagerMenuItem.addActionListener( 
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						externalPluginManager.showManagerDialog();			
					}
				} 
		);

		MenuItem themeChangeMenuItem = new MenuItem( "change theme" );
		themeChangeMenuItem.addActionListener( 
				new ActionListener() {
					@Override
					public void actionPerformed(ActionEvent e) {
						themeChanger.showThemeChangerDialog();			
					}
				} 
		);
		
		MenuItem calibtrateMessageWindowItem = new MenuItem( "calibrate message window" );
		calibtrateMessageWindowItem.addActionListener( calibrationAction );
		
		MenuItem aboutMenutItem = new MenuItem("show about");
		ActionListener aboutAction = new AboutAction();
		aboutMenutItem.addActionListener( aboutAction );
		
		return new MenuItem[]{
			pluginManagerMenuItem,
			new MenuItem("-"),
			themeChangeMenuItem,
			calibtrateMessageWindowItem,
			new MenuItem("-"),
			aboutMenutItem
		};
	}

	

	@Override
	protected Version getVersionImpl() {
		return MetaInformationService.readVersion();
	}

	@Override
	public boolean isFocusable() {
		return false;
	}


	@Override
	public void runPlugin(IPluginContext pluginContext) throws InterruptedException, PluginException {
		log.info( "now running..." );
		assertMessageWindowCalibtrated(pluginContext);
	}


	private void assertMessageWindowCalibtrated(IPluginContext pluginContext)
			throws PluginException {
		
		log.debug( "Check for initial setup for message window..." );
		CalibrationInfo calibrationInfo = load();
		boolean initCalibtration = calibrationInfo.isInitCalibration();
		if ( initCalibtration ) {
			log.info( "Initial setup for message window is necessary." );
			ActionEvent actionEvent = new ActionEvent( this, 0, "calibtration message window" );
			calibrationAction.actionPerformed( actionEvent );
		}
		else {
			log.debug( "no need to calibtrate message window" );
		}
	}

	@Override
	public String getFocus() {
		String focus = coreInfo.getFocus();
		return focus;
	}

	@Override
	public Theme getTheme() {
		Theme theme = coreInfo.getTheme();
		return theme;
	}
	

	@Override
	public void storeFocus(String pluginName) {
		coreInfo.setFocus( pluginName );
	}

	@Override
	public void storeTheme(Theme theme) {
		coreInfo.setTheme( theme );
	}

	public CoreInfo getCoreInfo() {
		CoreInfo coreInfo = null;
		
		try {
			coreInfo = context.getFileAccess().retrieve( CoreInfo.class );
		} catch (IOException e) {
			log.error( CAN_NOT_RETRIEVE_COREINFO, e );
			throw new InternalError( CAN_NOT_RETRIEVE_COREINFO );
		}
		
		return coreInfo;
	}
	
	
	public void storeCoreInfo(CoreInfo coreInfo) {
		try {
			context.getFileAccess().persist( coreInfo );
		} catch (IOException e) {
			log.error( CAN_NOT_STORE_COREINFO, e );
			throw new InternalError( CAN_NOT_STORE_COREINFO );
		}
	}
	

	@Override
	public void onPluginShutDownImpl() throws PluginException {
		storeCoreInfo( coreInfo );
	}


	@Override
	public CalibrationInfo load() throws PluginException {
		
		IPluginFileAccess fileAccess = context.getFileAccess();
		CalibrationInfo info;
		try {
			info = fileAccess.retrieve( CalibrationInfo.class );
			return info;
		} catch (IOException e) {
			String errorMessage = "can not retrieve calibtration info";
			log.error( errorMessage, e );
			throw new PluginException( errorMessage, e 	);
		}
	}


	@Override
	public void store(CalibrationInfo info) throws PluginException {
		IPluginFileAccess fileAccess = context.getFileAccess();
		try {
			fileAccess.persist( info );
		} catch (IOException e) {
			String errorMessage = "can not retrieve calibtration info";
			log.error( errorMessage, e );
			throw new PluginException( errorMessage, e 	);
		}
	}


	/**
	 * This method has been overridden.
	 * @see org.mopore.jat.core.fadingmessage.calibration.ICalibtrationAccessor#showConfirmMessage()
	 */
	@Override
	public void showConfirmMessage() {

		String title = "Calibration finished";
		String text = "Click into this message window if you wish to recalibrate.";
		Message message = new Message(  title, text, MessageType.INFO );
		
		context.showMessage( message, calibrationAction );
	}


	/**
	 * This method has been overridden.
	 * @see org.mopore.jat.core.ICore#showThemeChangeDialog()
	 */
	@Override
	public void showThemeChangeDialog() {
		themeChanger.showThemeChangerDialog();
	}


	/**
	 * This method has been overridden.
	 * @return
	 * @see org.mopore.jat.core.fadingmessage.calibration.ICalibtrationAccessor#getWindowController()
	 */
	@Override
	public IWindowController getWindowController() {
		return context.getWindowController();
	}




}
